/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package l1j.server.server.model.map;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.server.server.datatables.MapsTable;
import l1j.server.server.utils.FileUtil;
import l1j.server.server.utils.collections.Lists;
import l1j.server.server.utils.collections.Maps;

/**
 * 地圖 (maps/\d*.txt)讀取
 */
public class TextMapReader extends MapReader {

	/** 紀錄用 */
	private static Logger _log = Logger.getLogger(TextMapReader.class.getName());

	/** 地圖的路徑 */
	private static final String MAP_DIR = "./maps/";
	
	/** MAP_INFO 中編號的位置 */
	//public static final int MAPINFO_MAP_NO = 0;

	/** MAP_INFO 開始X座標的位置 */
	//public static final int MAPINFO_START_X = 1;

	/** MAP_INFO 結束X座標的位置 */
	//public static final int MAPINFO_END_X = 2;

	/** MAP_INFO 開始Y座標的位置 */
	//public static final int MAPINFO_START_Y = 3;

	/** MAP_INFO 結束Y座標的位置 */
	//public static final int MAPINFO_END_Y = 4;
	
	/**
	 * 依照輸入大小讀取指定編號地圖
	 * 
	 * @param mapId
	 *            地圖編號
	 * @param xSize
	 *            X座標大小
	 * @param ySize
	 *            Y座標大小
	 * @return byte[][]
	 * @throws IOException
	 */
	public byte[][] read(final int mapId, final int xSize, final int ySize)
			throws IOException {
		byte[][] map = new byte[xSize][ySize];
		LineNumberReader in = new LineNumberReader(new BufferedReader(
				new FileReader(MAP_DIR + mapId + ".txt")));

		int y = 0;
		String line;
		while ((line = in.readLine()) != null) {
			if ((line.trim().length() == 0) || line.startsWith("#")) {
				continue; // 跳過空行與註解
			}

			int x = 0;
			StringTokenizer tok = new StringTokenizer(line, ",");
			while (tok.hasMoreTokens()) {
				byte tile = Byte.parseByte(tok.nextToken());
				map[x][y] = tile;

				x++;
			}
			y++;
		}
		in.close();
		return map;
	}

	/**
	 * 讀取指定編號的地圖
	 * 
	 * @param id
	 *            地圖編號
	 * @return L1Map
	 * @throws IOException
	 */
	@Override
	public L1Map read(final int id) throws IOException {
		//get map's informations which include of startX, endX, startY and endY
		int[] mapSizeInfo = MapsTable.getInstance().getMapSizeInfo(id);
		
		if(mapSizeInfo == null){
			throw new FileNotFoundException("地圖編號: " + id);
		}
		
		int xSize = mapSizeInfo[1] - mapSizeInfo[0] + 1;
		int ySize = mapSizeInfo[3] - mapSizeInfo[2] + 1;
		
		int mapId = id;
		byte map[][] =  this.read(mapId, xSize, ySize);
		int worldTopLeftX = mapSizeInfo[0];
		int worldTopLeftY = mapSizeInfo[2];
		boolean underwater = MapsTable.getInstance().isUnderwater(mapId);
		boolean markable = MapsTable.getInstance().isMarkable(mapId); 
		boolean teleportable = MapsTable.getInstance().isTeleportable(mapId);
		boolean escapable = MapsTable.getInstance().isEscapable(mapId);
		boolean useResurrection = MapsTable.getInstance().isUseResurrection(mapId);
		boolean usePainwand = MapsTable.getInstance().isUsePainwand(mapId);
		boolean enabledDeathPenalty = MapsTable.getInstance().isEnabledDeathPenalty(mapId);
		boolean takePets = MapsTable.getInstance().isTakePets(mapId);
		boolean recallPets = MapsTable.getInstance().isRecallPets(mapId);
		boolean usableItem = MapsTable.getInstance().isUsableItem(mapId);
		boolean usableSkill = MapsTable.getInstance().isUsableSkill(mapId);
		
		return new L1V1Map(mapId, map, worldTopLeftX, worldTopLeftY,
				underwater, markable, teleportable, escapable, useResurrection,
				usePainwand, enabledDeathPenalty, takePets, recallPets,
				usableItem, usableSkill);
	}

	/**
	 * 取得所有地圖與編號的 Mapping
	 * 
	 * @return Map
	 * @throws IOException
	 */
	@Override
	public Map<Integer, L1Map> read() throws IOException {
		Map<Integer, L1Map> maps = Maps.newMap();
		
		//Loading all maps in ./map/*.txt
		for (int id : TextMapReader.listMapIds()) {
			maps.put(id, read(id));
		}
		
		return maps;
	}

	/**
	 * 傳回所有地圖的編號
	 * 
	 * @return ArraryList
	 */
	public static List<Integer> listMapIds() {
		List<Integer> ids = Lists.newList();

		File mapDir = new File(MAP_DIR);
		for (String name : mapDir.list()) {
			File mapFile = new File(mapDir, name);
			if (!mapFile.exists()) {
				continue;
			}
			if (!FileUtil.getExtension(mapFile).toLowerCase().equals("txt")) {
				continue;
			}
			int id = 0;
			try {
				String idStr = FileUtil.getNameWithoutExtension(mapFile);
				id = Integer.parseInt(idStr);
			} catch (NumberFormatException e) {
				continue;
			}
			ids.add(id);
		}
		return ids;
	}

}
